package com.mt.roll.common.service.impl;

import com.mt.roll.common.params.DownloadFileParam;
import com.mt.roll.common.params.UploadFileBase64Param;
import com.mt.roll.common.service.AttachmentService;
import com.mt.roll.common.vo.SysFileVo;
import com.mt.roll.core.base.BaseService;
import com.mt.roll.core.config.CommonConfig;
import com.mt.roll.core.dal.entity.SysFile;
import com.mt.roll.core.dal.service.SysFileServiceBiz;
import com.mt.roll.core.utils.*;
import com.mt.roll.core.vo.R;
import lombok.extern.log4j.Log4j2;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author jiff
 * @date 2021/1/12
 * @since 1.0
 */
@Log4j2
@Service
public class AttachmentServiceImpl extends BaseService implements AttachmentService {

    @Autowired
    private SysFileServiceBiz sysFileServiceBiz;
    @Autowired
    private CommonConfig commonConfig;

    /**
     * 文件上传(支持多文件上传)
     *
     * @param typeCode
     * @return
     */
    @Override
    public R<List<SysFileVo>> uploadFile(String typeCode) {
        //获取上传文件路径
        String uploadPath = commonConfig.getUploadPath() + typeCode + "/";
        log.debug("文件的上传路径：" + uploadPath);
        File file = new File(uploadPath);
        //判断文件是否存在，不存在则创建
        if (!file.exists()) {
            file.mkdirs();
        }
        List<SysFile> fileList = new ArrayList<>();
        //多文件上传
        CommonsMultipartResolver crm = new CommonsMultipartResolver(getHttpServletRequest().getSession().getServletContext());
        if (crm.isMultipart(getHttpServletRequest())) {
            MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) (getHttpServletRequest());
            Iterator<String> files = mRequest.getFileNames();
            log.debug("多文件" + files.toString());
            while (files.hasNext()) {
                MultipartFile mFile = mRequest.getFile(files.next());
                log.debug("文件" + mFile.toString());
                // 文件名
                String fileName = mFile.getOriginalFilename();
                //新文件名
                String newFileName = DateUtil.getCurrentDateTime() + RandomCodeGenerator.numericCode(4);
                // 文件扩展名
                String fileExtensionName = FileUtil.getExtensionName(fileName);
                //上传文件的真实路径
                String filePath = uploadPath + newFileName + "." + fileExtensionName;
                File localPath = new File(filePath);
                try {
                    mFile.transferTo(localPath);
                    //保存文件信息
                    SysFile sysFile = new SysFile();
                    sysFile.setTypeCode(typeCode);
                    sysFile.setFileUrl(filePath);
                    sysFile.setFileName(newFileName);
                    if (getLoginUser() != null) {
                        setCommonField(sysFile);
                    } else {
                        sysFile.setCreateTime(LocalDateTime.now());
                        sysFile.setCreator(1L);
                        sysFile.setCreatorName("system");
                    }
                    fileList.add(sysFile);
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("文件上传失败：" + e.getMessage());
                    return R.failed("文件上传失败");
                }
            }
        }
        sysFileServiceBiz.saveBatch(fileList);
        return R.ok(BeanUtils.copyList(fileList, SysFileVo.class));
    }

    /**
     * 文件上传
     *
     * @param uploadFileBase64Param 上传文件对象
     * @return
     */
    @Override
    public R<SysFileVo> uploadFileBase64(UploadFileBase64Param uploadFileBase64Param) {
        return null;
    }

    /**
     * 文件上传(form表单形式)
     *
     * @param typeCode
     * @param files
     * @return
     */
    @Override
    public R<List<SysFileVo>> uploadFileFormData(String typeCode, MultipartFile[] files) {
        //获取上传文件路径
        String uploadPath = commonConfig.getUploadPath() + typeCode + "/";
        log.debug("文件的上传路径：" + uploadPath);
        File file = new File(uploadPath);
        //判断文件是否存在，不存在则创建
        if (!file.exists()) {
            file.mkdirs();
        }
        List<SysFile> fileList = new ArrayList<>();
        for (MultipartFile multipartFile : files) {

            log.debug("上传文件" + multipartFile.toString());
            // 文件名
            String fileName = multipartFile.getOriginalFilename();
            //新文件名
            String newFileName = DateUtil.getCurrentDateTime() + RandomCodeGenerator.numericCode(4);
            // 文件扩展名
            String fileExtensionName = FileUtil.getExtensionName(fileName);
            //上传文件的真实路径
            String filePath = uploadPath + newFileName + "." + fileExtensionName;
            File localPath = new File(filePath);
            try {
                multipartFile.transferTo(localPath);
                //保存文件信息
                SysFile sysFile = new SysFile();
                sysFile.setTypeCode(typeCode);
                sysFile.setFileUrl(filePath);
                sysFile.setFileName(newFileName);
                if (getLoginUser() != null) {
                    setCommonField(sysFile);
                } else {
                    sysFile.setCreateTime(LocalDateTime.now());
                    sysFile.setCreator(1L);
                    sysFile.setCreatorName("system");
                }
                fileList.add(sysFile);
            } catch (Exception e) {
                e.printStackTrace();
                log.error("文件上传失败：" + e.getMessage());
                return R.failed("文件上传失败");
            }
        }

        sysFileServiceBiz.saveBatch(fileList);
        return R.ok(BeanUtils.copyList(fileList, SysFileVo.class));
    }

    /**
     * 文件下载（下载方式: 0、预览，1、下载）
     *
     * @param downloadFileParam
     * @return
     */
    @Override
    public R<Object> downloadFile(DownloadFileParam downloadFileParam) {
        //根据id获取附件信息
        SysFile sysFile = sysFileServiceBiz.getById(downloadFileParam.getAttachmentId());
        if (sysFile == null) {
            return R.failed("文件不存在");
        }
        HttpServletResponse response = getHttpServletResponse();
        // 文件路径
        String path = sysFile.getFileUrl();
        File file = new File(path);
        String fileName = file.getName();
        // 文件扩展名
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
        try {
            //判断下载方式是下载本地还是预览文件
            if (downloadFileParam.getType().equals("1")) {
                response.setContentType("application/octet-stream");
                response.setHeader("Content-Disposition", "attachment; filename=" + new String((StringUtils.isEmpty(downloadFileParam.getFileName()) ? sysFile.getFileName() + "." + suffix : downloadFileParam.getFileName() + "." + suffix).getBytes(Charset.forName("GBK")), StandardCharsets.ISO_8859_1));
            } else {
                URL u = new URL("file:///" + path);
                String contentType = u.openConnection().getContentType();
                response.setContentType(contentType);
                response.setHeader("Content-Disposition", "inline; filename=" + new String((StringUtils.isEmpty(downloadFileParam.getFileName()) ? sysFile.getFileName() + "." + suffix : downloadFileParam.getFileName() + "." + suffix).getBytes(Charset.forName("GBK")), StandardCharsets.ISO_8859_1));
            }
            //判断是否是图片格式
            ServletOutputStream outputStream = response.getOutputStream();
            if ("PNGpngJPGjpg".contains(suffix)) {
                Thumbnails.of(file)
                        .scale(downloadFileParam.getScale())
                        .outputQuality(downloadFileParam.getOutputQuality())
                        .toOutputStream(outputStream);
            } else {
                FileInputStream inputStream = new FileInputStream(file);
                byte[] buffer = new byte[1024];
                int i = -1;
                while ((i = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, i);
                }
                inputStream.close();
            }
            outputStream.flush();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("下载文件失败：{}", e.getMessage());
            return R.failed("下载文件失败");
        }
        return null;
    }
}
